﻿using OOXMLGenerator.DataStructure;
using System;
using System.IO;
using System.Drawing;
using System.Collections.Generic;

namespace Rzrlf.SP.Innovator.WebParts.StructureBrowserWebPart
{
    public partial class StructureBrowserWebPartUserControl : System.Web.UI.UserControl
    {
        #region Properties...

        private System.Collections.Generic.Dictionary<System.Web.UI.Control, string> _triggerControls = null;

        public System.Collections.Generic.Dictionary<System.Web.UI.Control, string> TriggerControls
        {
            get
            {
                return _triggerControls;
            }
        }

        #endregion

        #region Event Handlers...

        protected override void OnLoad(System.EventArgs e)
        {
            base.OnLoad(e);

            if (!base.IsPostBack)
            {
                string id = base.Request.QueryString["ID"];

                if (!string.IsNullOrEmpty(id))
                {
                    this.hdnCurrentItem.Value = Rzrlf.SP.Innovator.WebParts.Utils.IomUtil.GetPart(id);
                    this.hdnCurrentStructureXml.Value = Rzrlf.SP.Innovator.WebParts.Utils.IomUtil.GetPartBOM(id);
                }
            }

            this.TransformStructureXml();

            this.ManageDynamicControls(this.lblStructure.Controls);

            this.RestoreTreeState();
        }

        protected void OnCreateSite(object sender, System.EventArgs e)
        {
            string id;
            string itemNo;
            string rev;
            string siteName;
            string urlThumbnail;

            Microsoft.SharePoint.SPWeb web = this.GetWorkspace(out id, out itemNo, out rev, out urlThumbnail, out siteName);

            if (web != null)
            {
                this.RecordWorkspace(web, itemNo, rev, urlThumbnail);

                System.Collections.Generic.Dictionary<string, string> props = new System.Collections.Generic.Dictionary<string, string>();
                props.Add("url_workspace", siteName);

                System.Collections.Generic.Dictionary<string, string> attrs = new System.Collections.Generic.Dictionary<string, string>();
                attrs.Add("version", "0");

                Rzrlf.SP.Innovator.WebParts.Utils.IomUtil.UpdatePart(id, props, attrs);

                // begin: fme change                                
                string destUrl = web.Url + @"/Shared Documents/Summary Report of Part_" + siteName + ".xlsx";

                UploadExcelFile(Rzrlf.SP.Innovator.WebParts.Utils.IomUtil.GetIomInstance(), id, destUrl, Microsoft.SharePoint.SPContext.Current.Site.Url);
                // end: fme change

                base.Response.Redirect(web.Url);
            }
        }

        protected void OnInitChangeRequest(object sender, System.EventArgs e)
        {
            if (!string.IsNullOrEmpty(this.hdnCurrentItem.Value))
            {
                System.Xml.XPath.XPathDocument xmlDoc = new System.Xml.XPath.XPathDocument(new System.IO.StringReader(this.hdnCurrentItem.Value));

                System.Xml.XPath.XPathNavigator xmlNav = xmlDoc.CreateNavigator();

                System.Xml.XmlNamespaceManager xmlNsMgr = new System.Xml.XmlNamespaceManager(xmlNav.NameTable);
                xmlNsMgr.AddNamespace("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/");

                string id = xmlNav.SelectSingleNode("//SOAP-ENV:Envelope/SOAP-ENV:Body/Result/Item/id", xmlNsMgr).Value;

                string owner = xmlNav.SelectSingleNode("//SOAP-ENV:Envelope/SOAP-ENV:Body/Result/Item/owned_by_id/@keyed_name", xmlNsMgr).Value;

                string partNo = xmlNav.SelectSingleNode("//SOAP-ENV:Envelope/SOAP-ENV:Body/Result/Item/item_number", xmlNsMgr).Value;

                string url = string.Format("{0}/_layouts/FormServer.aspx?XsnLocation={1}/FormServerTemplates/Change Request.xsn&Source={2}/SitePages/Home.aspx&DefaultItemOpen=1&ID={3}&Owner={4}&PartNo={5}", new object[] { Microsoft.SharePoint.SPContext.Current.Web.Url, Microsoft.SharePoint.SPContext.Current.Web.Url, Microsoft.SharePoint.SPContext.Current.Web.Url, id, owner, partNo });

                base.Response.Redirect(url);
            }
        }

        protected void OnItemSelect(object sender, System.EventArgs e)
        {
            System.Web.UI.WebControls.LinkButton button = sender as System.Web.UI.WebControls.LinkButton;

            if (button != null)
            {
                System.Web.UI.WebControls.LinkButton prevButton = Rzrlf.SP.Innovator.WebParts.Utils.ControlUtil.FindControlRecursivelyByClientId(this.lblStructure, this.hdnSelectedClientId.Value) as System.Web.UI.WebControls.LinkButton;

                if (prevButton != null)
                {
                    prevButton.Style["font-weight"] = "normal";
                }

                button.Style["font-weight"] = "bold";

                this.hdnSelectedClientId.Value = button.ClientID;

                this.hdnCurrentItem.Value = Rzrlf.SP.Innovator.WebParts.Utils.IomUtil.GetPart(button.CommandArgument);
            }
        }

        #endregion

        #region Helper Methods...

        private Microsoft.SharePoint.SPList GetList(Microsoft.SharePoint.SPWeb web, string title)
        {
            foreach (Microsoft.SharePoint.SPList list in Microsoft.SharePoint.SPContext.Current.Web.Lists)
            {
                if (list.Title.Equals(title, System.StringComparison.OrdinalIgnoreCase))
                {
                    return list;
                }
            }

            return null;
        }

        private Microsoft.SharePoint.SPWeb GetWorkspace(out string id, out string itemNo, out string rev, out string urlThumbnail, out string siteName)
        {
            id = string.Empty;
            itemNo = string.Empty;
            rev = string.Empty;
            siteName = string.Empty;
            urlThumbnail = string.Empty;

            if (string.IsNullOrEmpty(this.hdnCurrentItem.Value))
            {
                return null;
            }

            System.Xml.XPath.XPathDocument xmlDoc = new System.Xml.XPath.XPathDocument(new System.IO.StringReader(this.hdnCurrentItem.Value));

            System.Xml.XPath.XPathNavigator xmlNav = xmlDoc.CreateNavigator();

            System.Xml.XmlNamespaceManager xmlNsMgr = new System.Xml.XmlNamespaceManager(xmlNav.NameTable);
            xmlNsMgr.AddNamespace("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/");

            id = xmlNav.SelectSingleNode("//SOAP-ENV:Envelope/SOAP-ENV:Body/Result/Item/id", xmlNsMgr).Value;

            itemNo = xmlNav.SelectSingleNode("//SOAP-ENV:Envelope/SOAP-ENV:Body/Result/Item/item_number", xmlNsMgr).Value;

            rev = xmlNav.SelectSingleNode("//SOAP-ENV:Envelope/SOAP-ENV:Body/Result/Item/major_rev", xmlNsMgr).Value;

            if (xmlNav.SelectSingleNode("//SOAP-ENV:Envelope/SOAP-ENV:Body/Result/Item/url_thumbnail", xmlNsMgr) != null)
            {
                urlThumbnail = xmlNav.SelectSingleNode("//SOAP-ENV:Envelope/SOAP-ENV:Body/Result/Item/url_thumbnail", xmlNsMgr).Value;

                if (!string.IsNullOrEmpty(urlThumbnail))
                {
                    if (urlThumbnail.StartsWith("/"))
                    {
                        urlThumbnail = string.Format("{0}{1}", Microsoft.SharePoint.SPContext.Current.Web.Url, urlThumbnail);
                    }
                    else
                    {
                        urlThumbnail = string.Format("{0}/{1}", Microsoft.SharePoint.SPContext.Current.Web.Url, urlThumbnail);
                    }
                }
            }

            siteName = string.Format("{0} - Rev {1}", itemNo, rev);

            if (Microsoft.SharePoint.SPContext.Current.Web.Webs[siteName].Exists)
            {
                return Microsoft.SharePoint.SPContext.Current.Web.Webs[siteName];
            }
            else
            {
                uint localeId = System.Convert.ToUInt32(1033);

                Microsoft.SharePoint.SPWebTemplateCollection templates = Microsoft.SharePoint.SPContext.Current.Site.GetWebTemplates(localeId);

                foreach (Microsoft.SharePoint.SPWebTemplate template in templates)
                {
                    if (template.Title.Equals("Part Workspace", StringComparison.OrdinalIgnoreCase))
                    {
                        System.Guid newSiteId = System.Guid.Empty;

                        string newSiteName = siteName;

                        Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(delegate()
                        {
                            using (Microsoft.SharePoint.SPSite site = new Microsoft.SharePoint.SPSite(Microsoft.SharePoint.SPContext.Current.Site.ID))
                            {
                                using (Microsoft.SharePoint.SPWeb web = site.OpenWeb())
                                {
                                    web.AllowUnsafeUpdates = true;
                                    Microsoft.SharePoint.SPWeb newWeb = web.Webs.Add(newSiteName, newSiteName, string.Empty, localeId, template, false, false);

                                    newSiteId = newWeb.ID;
                                    
                                    newWeb.Dispose();
                                }
                            }
                        });

                        return Microsoft.SharePoint.SPContext.Current.Web.Webs[newSiteId];
                    }
                }

                throw new System.ArgumentException("'Part Workspace' template not found.");
            }
        }

        private void ManageDynamicControls(System.Web.UI.ControlCollection controls)
        {
            for (int i = 0; i < controls.Count; i++)
            {
                System.Web.UI.WebControls.LinkButton button = controls[i] as System.Web.UI.WebControls.LinkButton;

                if (button != null)
                {
                    button.Click += new System.EventHandler(this.OnItemSelect);

                    if (!base.IsPostBack && string.IsNullOrEmpty(this.hdnSelectedClientId.Value))
                    {
                        this.hdnSelectedClientId.Value = button.ClientID;
                    }

                    if (button.ClientID.Equals(this.hdnSelectedClientId.Value, System.StringComparison.OrdinalIgnoreCase))
                    {
                        button.Style["font-weight"] = "bold";
                    }
                    else
                    {
                        button.Style["font-weight"] = "normal";
                    }

                    if (_triggerControls == null)
                    {
                        _triggerControls = new System.Collections.Generic.Dictionary<System.Web.UI.Control, string>();
                    }
                    _triggerControls.Add(button, "ItemSelectionChanged");
                }
                else
                {
                    this.ManageDynamicControls(controls[i].Controls);
                }
            }
        }

        private void RecordWorkspace(Microsoft.SharePoint.SPWeb web, string itemNo, string rev, string urlThumbnail)
        {
            Microsoft.SharePoint.SPList list = this.GetList(Microsoft.SharePoint.SPContext.Current.Web, "Workspaces");

            if (list == null)
            {
                System.Guid listId = Microsoft.SharePoint.SPContext.Current.Web.Lists.Add("Workspaces", "Represents a list of all Innovator part-centric workspaces", Microsoft.SharePoint.SPContext.Current.Web.ListTemplates["Custom List"]);

                list = Microsoft.SharePoint.SPContext.Current.Web.Lists[listId];
                list.Fields.Add("ItemNumber", Microsoft.SharePoint.SPFieldType.Text, true);
                list.Fields.Add("Revision", Microsoft.SharePoint.SPFieldType.Text, true);
                list.Fields.Add("SiteUrl", Microsoft.SharePoint.SPFieldType.URL, true);
                list.Fields.Add("Thumbnail", Microsoft.SharePoint.SPFieldType.URL, false);
                (list.Fields["Thumbnail"] as Microsoft.SharePoint.SPFieldUrl).DisplayFormat = Microsoft.SharePoint.SPUrlFieldFormatType.Image;
                list.OnQuickLaunch = true;
                list.Update();

                Microsoft.SharePoint.SPView view = list.DefaultView;
                view.ViewFields.DeleteAll();
                view.ViewFields.Add("ItemNumber");
                view.ViewFields.Add("Revision");
                view.ViewFields.Add("SiteUrl");
                view.ViewFields.Add("Thumbnail");
                view.Update();
            }

            string url = string.Format("{0}, {1}", web.Url, web.Url);

            bool urlExists = false;

            foreach (Microsoft.SharePoint.SPListItem item in list.Items)
            {
                if (item["SiteUrl"].ToString().Equals(url, System.StringComparison.OrdinalIgnoreCase))
                {
                    urlExists = true;

                    break;
                }
            }

            if (!urlExists)
            {
                Microsoft.SharePoint.SPListItem item = list.AddItem();
                item["ItemNumber"] = itemNo;
                item["Revision"] = rev;
                item["SiteUrl"] = web.Url;
                item["Thumbnail"] = urlThumbnail;
                item.Update();
            }
        }

        private void RestoreTreeState()
        {
            System.Text.StringBuilder script = new System.Text.StringBuilder();

            string[] ids = this.hdnCollapsedIds.Value.Split(char.Parse(","));

            foreach (string id in ids)
            {
                if (!string.IsNullOrEmpty(id))
                {
                    string commonId = id.Substring(3);

                    script.AppendLine(string.Format("document.getElementById('div{0}').style.display = 'none';", commonId));
                    script.AppendLine(string.Format("document.getElementById('img{0}').src = '~/_layouts/images/Rzrlf.SP.Innovator.WebParts/Expand8x8.png';", commonId));
                }
            }

            if (script.Length > 0)
            {
                System.Web.UI.ScriptManager.RegisterStartupScript(this, this.GetType(), "RestoreTreeState", script.ToString(), true);
            }
        }

        private void TransformStructureXml()
        {
            string xml = (string)this.hdnCurrentStructureXml.Value;

            if (string.IsNullOrEmpty(xml))
            {
                this.lblStructure.Text = "No item specified";
            }
            else
            {
                System.Xml.XPath.XPathDocument xmlDoc = new System.Xml.XPath.XPathDocument(new System.IO.StringReader(xml));

                System.Xml.Xsl.XslCompiledTransform xslDoc = new System.Xml.Xsl.XslCompiledTransform();
                xslDoc.Load(base.Request.MapPath("/_layouts/Rzrlf.SP.Innovator.WebParts/Structure.xslt"));

                System.IO.StringWriter writer = new System.IO.StringWriter();
                xslDoc.Transform(xmlDoc, null, writer);

                string content = writer.ToString();
                content = content.Replace("xmlns:asp=\"remove\"", string.Empty);

                System.Web.UI.Control ctrl = base.ParseControl(content);

                this.lblStructure.Controls.Add(ctrl);
            }
        }

        // begin: fme change
        private void UploadExcelFile(Aras.IOM.Innovator innovator, string id, string destUrl, string rootUrl)
        {
            bool? fileExists = FileExists(destUrl);
            if (fileExists.HasValue && !((bool)fileExists))
            {
                Stream stream;
                string error = "";

                Image partImage = GetPartThumbnailImage(rootUrl);
                List<SectionContent> sectionContentList = new List<SectionContent>();
                CRSectionContent crSectionContent = GetChangeRequests(id, rootUrl);
                if (crSectionContent != null)
                    sectionContentList.Add(crSectionContent);
                OOXMLGenerator.Report.ExcelReportGenerator.Generate(innovator, id, partImage, ref error, out stream, sectionContentList, true);
                UploadStream(stream, destUrl);
            }
        }

        private string GetPartThumbnailUrl()
        {
            if (string.IsNullOrEmpty(this.hdnCurrentItem.Value))
                return string.Empty;

            System.Xml.XPath.XPathDocument xmlDoc = new System.Xml.XPath.XPathDocument(new System.IO.StringReader(this.hdnCurrentItem.Value));
            System.Xml.XPath.XPathNavigator xmlNav = xmlDoc.CreateNavigator();
            System.Xml.XmlNamespaceManager xmlNsMgr = new System.Xml.XmlNamespaceManager(xmlNav.NameTable);

            xmlNsMgr.AddNamespace("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/");

            string thumbnailUrl = xmlNav.SelectSingleNode("//SOAP-ENV:Envelope/SOAP-ENV:Body/Result/Item/url_thumbnail", xmlNsMgr).Value;

            return thumbnailUrl;
        }

        private Image GetPartThumbnailImage(string rootUrl)
        {
            System.Drawing.Image partImage = null;

            //string imgUrl = "http://fme-dcsql01/Vendetta_Thumbnails/batt_pack_alka_x803314.asm.1.jpg";

            string relativeThumbnailUrl = GetPartThumbnailUrl();

            if (!string.IsNullOrEmpty(relativeThumbnailUrl))
            {
                string partImageUrl = rootUrl + (relativeThumbnailUrl.StartsWith("/") ? "" : "/") + relativeThumbnailUrl;

                using (Microsoft.SharePoint.SPWeb webImage = new Microsoft.SharePoint.SPSite(partImageUrl).OpenWeb())
                {
                    Microsoft.SharePoint.SPFile file = webImage.GetFile(partImageUrl);
                    if (file.Exists)
                    {
                        byte[] imgBytes = file.OpenBinary();
                        if (imgBytes != null && imgBytes.Length > 0)
                        {
                            MemoryStream ms = new MemoryStream(imgBytes);
                            partImage = System.Drawing.Image.FromStream(ms);
                        }
                    }
                }
            }
            return partImage;
        }

        private bool? FileExists(string destUrl)
        {
            bool? fileExists = null;
            using (Microsoft.SharePoint.SPWeb web = new Microsoft.SharePoint.SPSite(destUrl).OpenWeb())
            {
                fileExists = web.GetFile(destUrl).Exists;
            }
            return fileExists;
        }

        private void UploadStream(System.IO.Stream stream, string destUrl)
        {
            if (stream != null)
            {
                byte[] bytes = ((System.IO.MemoryStream)stream).ToArray();
                using (Microsoft.SharePoint.SPWeb web = new Microsoft.SharePoint.SPSite(destUrl).OpenWeb())
                {
                    if (!web.GetFile(destUrl).Exists)
                    {
                        EnsureParentFolder(web, destUrl);
                        web.Files.Add(destUrl, bytes);
                    }
                }
            }
        }

        private string EnsureParentFolder(Microsoft.SharePoint.SPWeb parentSite, string destUrl)
        {
            destUrl = parentSite.GetFile(destUrl).Url;
            int index = destUrl.LastIndexOf("/");
            string parentFolderUrl = string.Empty;
            if (index > -1)
            {
                parentFolderUrl = destUrl.Substring(0, index);
                Microsoft.SharePoint.SPFolder parentFolder = parentSite.GetFolder(parentFolderUrl);
                if (!parentFolder.Exists)
                {
                    Microsoft.SharePoint.SPFolder currentFolder = parentSite.RootFolder;
                    foreach (string folder in parentFolderUrl.Split('/'))
                    {
                        currentFolder = currentFolder.SubFolders.Add(folder);
                    }
                }
            }
            return parentFolderUrl;
        }

        private Microsoft.SharePoint.SPListItemCollection GetChangeRequestsSPListItems(string partID, string rootUrl)
        {
            Microsoft.SharePoint.SPListItemCollection changeRequestsListCollection = null;
            using (Microsoft.SharePoint.SPSite site = new Microsoft.SharePoint.SPSite(rootUrl))
            {
                Microsoft.SharePoint.SPList listCR = site.RootWeb.Lists["Change Requests"];

                Microsoft.SharePoint.SPQuery crQuery = new Microsoft.SharePoint.SPQuery();

                string query = string.Format("<Where><Eq><FieldRef Name='{0}' /><Value Type='Text'>{1}</Value></Eq></Where>",
                    listCR.Fields["Part Id"].InternalName, partID);
                crQuery.Query = query;

                try
                {
                    changeRequestsListCollection = listCR.GetItems(crQuery);
                }
                catch (System.Exception)
                {
                    // TODO: handle exception
                    throw;
                }
                return changeRequestsListCollection;
            }
        }

        private CRSectionContent GetChangeRequestsSection(Microsoft.SharePoint.SPListItemCollection crListItems, string rootUrl)
        {
            CRSectionContent crSection = null;
            if (crListItems != null && crListItems.Count > 0)
            {
                crSection = new CRSectionContent();
                DateTime? date = null;
                DateTime auxDate;
                string requested = string.Empty, description = string.Empty, status = string.Empty;

                using (Microsoft.SharePoint.SPSite site = new Microsoft.SharePoint.SPSite(rootUrl))
                {
                    Microsoft.SharePoint.SPList list = site.RootWeb.Lists["Change Requests"];

                    foreach (Microsoft.SharePoint.SPListItem crItem in crListItems)
                    {

                        if (DateTime.TryParse(crItem.GetFormattedValue(list.Fields["Created"].InternalName), out auxDate))
                            date = auxDate;
                        else
                            date = null;
                        requested = crItem.GetFormattedValue(list.Fields["Owner"].InternalName);
                        description = crItem.GetFormattedValue(list.Fields["Description"].InternalName);
                        status = crItem.GetFormattedValue(list.Fields["Change Request Workflow"].InternalName);
                        crSection.AddCRItem(date, requested, description, status);
                    }
                }
            }
            return crSection;
        }

        private CRSectionContent GetChangeRequests(string partID, string rootUrl)
        {
            CRSectionContent crSectionContent = null;
            Microsoft.SharePoint.SPListItemCollection crSPListItems = GetChangeRequestsSPListItems(partID, rootUrl);
            if (crSPListItems != null)
                crSectionContent = GetChangeRequestsSection(crSPListItems, rootUrl);
            return crSectionContent;
        }
        // end: fme change

        #endregion
    }
}